import pygame
import os
import json
from typing import Dict, Any, Optional
from pygame import Surface, mixer


class ResourceManager:
    """Manages all game resources including images, audio, video, and text files"""
    
    def __init__(self, base_path: str = "resources"):
        self.base_path = base_path
        self.images: Dict[str, Surface] = {}
        self.sounds: Dict[str, mixer.Sound] = {}
        self.music: Dict[str, str] = {}
        self.texts: Dict[str, str] = {}
        self.data: Dict[str, Any] = {}
        
    def load_image(self, name: str, filename: str, convert_alpha: bool = True) -> Surface:
        """Load and cache an image"""
        if name not in self.images:
            path = os.path.join(self.base_path, "images", filename)
            if os.path.exists(path):
                image = pygame.image.load(path)
                if convert_alpha:
                    image = image.convert_alpha()
                else:
                    image = image.convert()
                self.images[name] = image
            else:
                raise FileNotFoundError(f"Image file not found: {path}")
        return self.images[name]
        
    def get_image(self, name: str) -> Optional[Surface]:
        """Get a cached image"""
        return self.images.get(name)
        
    def load_sound(self, name: str, filename: str) -> mixer.Sound:
        """Load and cache a sound effect"""
        if name not in self.sounds:
            path = os.path.join(self.base_path, "audio", filename)
            if os.path.exists(path):
                sound = mixer.Sound(path)
                self.sounds[name] = sound
            else:
                raise FileNotFoundError(f"Sound file not found: {path}")
        return self.sounds[name]
        
    def get_sound(self, name: str) -> Optional[mixer.Sound]:
        """Get a cached sound"""
        return self.sounds.get(name)
        
    def load_music(self, name: str, filename: str) -> None:
        """Register a music file path"""
        path = os.path.join(self.base_path, "audio", filename)
        if os.path.exists(path):
            self.music[name] = path
        else:
            raise FileNotFoundError(f"Music file not found: {path}")
            
    def play_music(self, name: str, loops: int = -1) -> None:
        """Play background music"""
        if name in self.music:
            mixer.music.load(self.music[name])
            mixer.music.play(loops)
            
    def load_text(self, name: str, filename: str) -> str:
        """Load and cache a text file"""
        if name not in self.texts:
            path = os.path.join(self.base_path, "text", filename)
            if os.path.exists(path):
                with open(path, 'r', encoding='utf-8') as f:
                    text = f.read()
                self.texts[name] = text
            else:
                raise FileNotFoundError(f"Text file not found: {path}")
        return self.texts[name]
        
    def get_text(self, name: str) -> Optional[str]:
        """Get cached text"""
        return self.texts.get(name)
        
    def load_json(self, name: str, filename: str) -> Dict[str, Any]:
        """Load and cache JSON data"""
        if name not in self.data:
            path = os.path.join(self.base_path, "text", filename)
            if os.path.exists(path):
                with open(path, 'r', encoding='utf-8') as f:
                    data = json.load(f)
                self.data[name] = data
            else:
                raise FileNotFoundError(f"JSON file not found: {path}")
        return self.data[name]
        
    def get_data(self, name: str) -> Optional[Dict[str, Any]]:
        """Get cached JSON data"""
        return self.data.get(name)
        
    def clear_cache(self) -> None:
        """Clear all cached resources"""
        self.images.clear()
        self.sounds.clear()
        self.music.clear()
        self.texts.clear()
        self.data.clear()
        
    def preload_resources(self, resource_list: Dict[str, Dict[str, str]]) -> None:
        """Preload multiple resources from a configuration dictionary"""
        for resource_type, resources in resource_list.items():
            for name, filename in resources.items():
                if resource_type == "images":
                    self.load_image(name, filename)
                elif resource_type == "sounds":
                    self.load_sound(name, filename)
                elif resource_type == "music":
                    self.load_music(name, filename)
                elif resource_type == "texts":
                    self.load_text(name, filename)
                elif resource_type == "data":
                    self.load_json(name, filename)